package com.example.jobback.service.manager.impl;

import com.alibaba.fastjson.JSON;
import com.example.jobback.common.enums.PositionStatus;
import com.example.jobback.common.enums.VerifyPublishPositionStatus;
import com.example.jobback.config.AuthConfig;
import com.example.jobback.dto.PositionDto;
import com.example.jobback.dto.PublishPositionDto;
import com.example.jobback.dto.UpdatePositionDto;
import com.example.jobback.po.*;
import com.example.jobback.req.recruiter.position.update.RCrossChangePositionReq;
import com.example.jobback.resp.manager.position.GetPositionMessageResp;
import com.example.jobback.resp.manager.position.page.MCrossGetPagePositionResp;
import com.example.jobback.resp.manager.position.page.MCrossGetPagePositionsResp;
import com.example.jobback.resp.manager.position.publish.ManagerPendingPubJobResp;
import com.example.jobback.resp.manager.position.update.ManagerPendingUpdateJobResp;
import com.example.jobback.resp.manager.position.update.PositionMessageResp;
import com.example.jobback.resp.seeker.common.page.SCrossGetPageSeekersResp;
import com.example.jobback.result.Result;
import com.example.jobback.service.common.UserCommonService;
import com.example.jobback.service.manager.ManagerPositionService;
import com.example.jobback.service.recruiter.RecruiterCrossService;
import com.example.jobback.util.CACHEUtil;
import com.example.jobback.util.CrossServiceInvoker;
import com.example.jobback.util.PhoneNumberUtils;
import com.example.jobback.util.TLUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.example.jobback.util.RedisConstants.*;
import static com.example.jobback.util.RedisConstants.MANAGER_TTL;

/**
 * @ClassName: ManagerPositionServiceImpl
 * @Description:管理员-岗位管理服务实现类
 * @Author: lhb
 * @Date: 2025/6/21
 */
@Service
public class ManagerPositionServiceImpl implements ManagerPositionService {


    @Value("${cross_service_baseurl}")
    private String crossServiceBaseUrl;

    private final RecruiterCrossService recruiterCrossService;

    private final CACHEUtil cacheUtil;


    private final RestTemplate restTemplate;

    private final UserCommonService userCommonService;

    private final PhoneNumberUtils phoneNumberUtils;

    private final AuthConfig authConfig;

    public ManagerPositionServiceImpl(CACHEUtil cacheUtil, UserCommonService userCommonService, AuthConfig authConfig, RestTemplate restTemplate, RecruiterCrossService recruiterCrossService, PhoneNumberUtils phoneNumberUtils) {
        this.cacheUtil = cacheUtil;
        this.userCommonService = userCommonService;
        this.authConfig = authConfig;
        this.restTemplate = restTemplate;
        this.recruiterCrossService = recruiterCrossService;
        this.phoneNumberUtils = phoneNumberUtils;
    }

    /**
     * @Description: 获取发布待审核岗位的列表
     * @return Result<List<ManagerPendingPubJobResp>>
     * @Author lhb
     * @CreateTime 2025/6/21 16:32
     */
    @Override
    public Result<List<ManagerPendingPubJobResp>> getPublishPositionLists() {
        List<ManagerPendingPubJobResp> respList=new ArrayList<>();
        //获取code集合
        Set<String> codesByRank = cacheUtil.getMembersByRank(VERIFY_RECRUITER_PUBLISH_POSITION_MANAGER_CODE_KEY, 0, -1);
        if(codesByRank.isEmpty()) return Result.success(respList);
        List<String> codeList = new ArrayList<>(codesByRank);
        //包装keys集合
        List<String> keys = codesByRank.stream()
                .map(member -> VERIFY_RECRUITER_PUBLISH_POSITION_KEY + member)
                .collect(Collectors.toList());
        List<String> dtoJsons = cacheUtil.multiGet(keys);
        if(dtoJsons.isEmpty()) {
            return Result.success(respList);
        }
        List<Long> userIds=new ArrayList<>();
        // 使用索引同步遍历 codeList 和 dtoJsons
        for (int i = 0; i < dtoJsons.size(); i++) {
            String dtoJson = dtoJsons.get(i);
            if (dtoJson == null) continue;
            PublishPositionDto dto = JSON.parseObject(dtoJson, PublishPositionDto.class);
            userIds.add(dto.getUserId());
            ManagerPendingPubJobResp resp = new ManagerPendingPubJobResp();
            // 复制属性
            BeanUtils.copyProperties(dto, resp);
            // 设置对应的 code（来自 codeList）
            resp.setCode(codeList.get(i));
            respList.add(resp);
        }
        List<User> users = userCommonService.getUsersByUserIds(userIds);
        // 将 users 转换为 Map
        Map<Long, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getUserId, user -> user));
        // 遍历 respList 并设置 name
        respList.forEach(resp -> {
            User user = userMap.get(resp.getUserId());
            if (user != null) {
                resp.setName(user.getName());
            }
        });
        return Result.success(respList);
    }

    /**
     * @Description: 审核发布岗位不通过
     * @param code
     * @param failMessage
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 16:35
     */
    @Override
    public Result<Object> verifyPublishPositionFailed(String code, String failMessage) {
        Manager manager= TLUtil.get(TLUtil.M);
        String dtoJson = cacheUtil.get(VERIFY_RECRUITER_PUBLISH_POSITION_KEY + code);
        PublishPositionDto dto = JSON.parseObject(dtoJson, PublishPositionDto.class);
        if (!dto.getStatus().equals(VerifyPublishPositionStatus.VERIFY_MANAGER_REVIEW)) {
            throw new RuntimeException("未在管理员审核名单中");
        }
        //修改职位信息
        dto.setStatus(VerifyPublishPositionStatus.VERIFY_MANAGER_FAILED);
        dto.setFailedMessage(failMessage);
        String dtoNewJson = JSON.toJSONString(dto);
        cacheUtil.setNoTtl(VERIFY_RECRUITER_PUBLISH_POSITION_KEY+code,dtoNewJson);
        //删除在manager-code的记录
        cacheUtil.removeMember(VERIFY_RECRUITER_PUBLISH_POSITION_MANAGER_CODE_KEY,code);
        //延时登录态
        String token=userCommonService.updateRedisUserToken(manager.getUserId(),MANAGER_KEY,authConfig.getJwtManagerSecret(),MANAGER_TTL, TimeUnit.DAYS);
        return Result.success(token);
    }

    /**
     * @Description: 审核发布岗位通过
     * @param code
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 16:38
     */
    @Override
    public Result<Object> verifyPublishPosition(String code) {
        Manager manager=TLUtil.get(TLUtil.M);
        Long userId=manager.getUserId();
        String dtoJson = cacheUtil.get(VERIFY_RECRUITER_PUBLISH_POSITION_KEY + code);
        if(dtoJson==null) throw new RuntimeException("未在管理审核名单中");
        PublishPositionDto dto = JSON.parseObject(dtoJson, PublishPositionDto.class);
        Long companyId=dto.getCompanyId();
        if (!dto.getStatus().equals(VerifyPublishPositionStatus.VERIFY_MANAGER_REVIEW)){
            throw new RuntimeException("未在管理审核名单中");
        }
        //跨服务注册岗位信息，招聘写接口
        if(!registerPublishPosition(dto,userId)){
            throw new RuntimeException("注册失败");
        }
        //删除redis记录
        //manager-code
        cacheUtil.removeMember(VERIFY_RECRUITER_PUBLISH_POSITION_MANAGER_CODE_KEY,code);
        //com-code
        cacheUtil.removeMember(VERIFY_RECRUITER_PUBLISH_POSITION_COM_CODE_KEY+companyId,code);
        //recruiter-code
        Long recruiterUserId=dto.getUserId();
        cacheUtil.removeMember(VERIFY_RECRUITER_PUBLISH_POSITION_RECRUITER_CODE_KEY+recruiterUserId,code);
        //删除职位信息redis记录
        cacheUtil.deleteKeySafely(VERIFY_RECRUITER_PUBLISH_POSITION_KEY+code);
        //延时登录态
        String token=userCommonService.updateRedisUserToken(manager.getUserId(),MANAGER_KEY,authConfig.getJwtManagerSecret(),MANAGER_TTL,TimeUnit.DAYS);
        if(token==null) throw new RuntimeException("token生成失败");
        return Result.success(token);
    }

    /**
     * @Description: 获取变更待审核岗位的列表
     * @return Result<List<ManagerPendingUpdateJobResp>>
     * @Author lhb
     * @CreateTime 2025/6/21 16:45
     */
    @Override
    public Result<List<ManagerPendingUpdateJobResp>> getUpdatedPositionLists() {
        List<ManagerPendingUpdateJobResp> respList=new ArrayList<>();
        Set<String> positionIdByRank = cacheUtil.getMembersByRank(VERIFY_RECRUITER_UPDATE_POSITION_MANAGER_ID_KEY, 0, -1);
        if(positionIdByRank.isEmpty()) return Result.success(respList);
        //包装keys集合
        List<String> keys = positionIdByRank.stream()
                .map(member -> VERIFY_RECRUITER_UPDATE_POSITION_KEY + member)
                .collect(Collectors.toList());
        List<String> dtoJsons = cacheUtil.multiGet(keys);
        if(dtoJsons.isEmpty()) {
            return Result.success(respList);
        }
        List<Long> userIds=new ArrayList<>();
        for(String dtoJson:dtoJsons){
            UpdatePositionDto dto = JSON.parseObject(dtoJson, UpdatePositionDto.class);
            if(!dto.getStatus().equals(PositionStatus.VERIFY_MANAGER_REVIEW)) continue;
            //构造userId
            userIds.add(dto.getOldDto().getUserId());
            ManagerPendingUpdateJobResp resp=new ManagerPendingUpdateJobResp();
            // 确保 oldPositionMessage 和 newPositionMessage 已经初始化
            resp.setOldPositionMessage(new PositionMessageResp());
            resp.setNewPositionMessage(new PositionMessageResp());
            //字段映射
            BeanUtils.copyProperties(dto.getOldDto(),resp.getOldPositionMessage());
            BeanUtils.copyProperties(dto.getNewDto(),resp.getNewPositionMessage());
            respList.add(resp);
        }
        List<User> users = userCommonService.getUsersByUserIds(userIds);
        // 将 users 转换为 Map
        Map<Long, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getUserId, user -> user));
        // 遍历 respList 并设置 name
        respList.forEach(resp -> {
            User user = userMap.get(resp.getOldPositionMessage().getUserId());
            if (user != null) {
                resp.getOldPositionMessage().setName(user.getName());
                resp.getNewPositionMessage().setName(user.getName());
            }
        });
        return Result.success(respList);
    }

    /**
     * @Description: 审核岗位变更通过
     * @param positionId
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 16:46
     */
    @Override
    public Result<Object> VerifyChangePosition(Long positionId) {
        Manager manager = TLUtil.get(TLUtil.M);
        Long userId=manager.getUserId();
        boolean memberInZSet = cacheUtil.isMemberInZSet(VERIFY_RECRUITER_UPDATE_POSITION_MANAGER_ID_KEY , positionId.toString());
        if(!memberInZSet) throw new IllegalArgumentException("VALIDATION_ERROR：无该岗位变更信息");
        String dtoJson = cacheUtil.get(VERIFY_RECRUITER_UPDATE_POSITION_KEY + positionId);
        if(dtoJson==null) throw new IllegalArgumentException("VALIDATION_ERROR：无该岗位变更信息");
        UpdatePositionDto dto = JSON.parseObject(dtoJson, UpdatePositionDto.class);
        if(!dto.getStatus().equals(PositionStatus.VERIFY_MANAGER_REVIEW)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：岗位状态异常");
        }
        //构造请求体
        PositionDto newDto = dto.getNewDto();
        RCrossChangePositionReq req=new RCrossChangePositionReq();
        BeanUtils.copyProperties(newDto,req);
        //跨服务调用
        try {
            if(!changePositionInformation(req,userId)) throw new RuntimeException("注册失败");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        //删除redis记录
        Long recruiterUserId=newDto.getUserId();
        Long companyId=newDto.getCompanyId();
        cacheUtil.removeMember(VERIFY_RECRUITER_UPDATE_POSITION_MANAGER_ID_KEY,positionId.toString());
        cacheUtil.removeMember(VERIFY_RECRUITER_UPDATE_POSITION_RECRUITER_ID_KEY+recruiterUserId,positionId.toString());
        cacheUtil.removeMember(VERIFY_RECRUITER_UPDATE_POSITION_COM_ID_KEY+companyId,positionId.toString());
        cacheUtil.deleteKeySafely(VERIFY_RECRUITER_UPDATE_POSITION_KEY+positionId);
        //延时登录态
        String token=userCommonService.updateRedisUserToken(manager.getUserId(),MANAGER_KEY,authConfig.getJwtManagerSecret(),MANAGER_TTL,TimeUnit.DAYS);
        if(token==null) throw new RuntimeException("token生成失败");
        return Result.success(token);
    }

    /**
     * @Description: 审核岗位变更不通过
     * @param positionId
     * @param failedMessage
     * @return Result<Object>
     * @Author lhb
     * @CreateTime 2025/6/21 16:49
     */
    @Override
    public Result<Object> VerifyChangePositionFailed(Long positionId, String failedMessage) {
        Manager manager = TLUtil.get(TLUtil.M);
        boolean memberInZSet = cacheUtil.isMemberInZSet(VERIFY_RECRUITER_UPDATE_POSITION_MANAGER_ID_KEY , positionId.toString());
        if(!memberInZSet) throw new IllegalArgumentException("VALIDATION_ERROR：无该岗位变更信息");
        String dtoJson = cacheUtil.get(VERIFY_RECRUITER_UPDATE_POSITION_KEY + positionId);
        if(dtoJson==null) throw new IllegalArgumentException("VALIDATION_ERROR：无该岗位变更信息");
        UpdatePositionDto dto = JSON.parseObject(dtoJson, UpdatePositionDto.class);
        if(!dto.getStatus().equals(PositionStatus.VERIFY_MANAGER_REVIEW)) {
            throw new IllegalArgumentException("VALIDATION_ERROR：岗位状态异常");
        }
        //修改redis记录
        dto.setStatus(PositionStatus.VERIFY_MANAGER_FAILED);
        dto.setFailMessage(failedMessage);
        String dtoNewJson = JSON.toJSONString(dto);
        //更新岗位信息，从manager的set中删除其positionId
        cacheUtil.setNoTtl(VERIFY_RECRUITER_UPDATE_POSITION_KEY+positionId,dtoNewJson);
        cacheUtil.removeMember(VERIFY_RECRUITER_UPDATE_POSITION_MANAGER_ID_KEY,positionId.toString());
        //延时登录态
        String token=userCommonService.updateRedisUserToken(manager.getUserId(),MANAGER_KEY,authConfig.getJwtManagerSecret(),MANAGER_TTL,TimeUnit.DAYS);
        if(token==null) throw new RuntimeException("token生成失败");
        return Result.success(token);
    }

    /**
     * @Description: 分页查询职位列表
     * @param page
     * @param size
     * @param content
     * @return Result<MCrossGetPagePositionsResp>
     * @Author lhb
     * @CreateTime 2025/7/12 19:01
     */
    @Override
    public Result<MCrossGetPagePositionsResp> getPositions(int page, int size, String content) {
        MCrossGetPagePositionsResp resp = new MCrossGetPagePositionsResp();
        PageInfo<Position> positionPageInfo = recruiterCrossService.getPositions(page,size,content);
        List<Position> positions = positionPageInfo.getList();
        if(positions.isEmpty()) {
            resp.setPages(0);
            resp.setTotal(0L);
            resp.setPageNum(0);
            resp.setPageSize(0);
            resp.setSize(0);
            resp.setRespList(new ArrayList<>());
            return Result.success(resp);
        }
        //获取userid查找user对象
        List<Long> userIds = positions.stream()
                .map(Position::getUserId)
                .filter(Objects::nonNull)
                .toList();
        List<User> users = userCommonService.getUsersByUserIds(userIds);
        //处理分页查询管理员列表响应体
        resp=processPagePositionList(positions, users,positionPageInfo);
        return Result.success(resp);
    }

    /**
     * @Description: 查看职位详细
     * @param positionId
     * @return Result<GetPositionMessageResp>
     * @Author lhb
     * @CreateTime 2025/7/12 20:41
     */
    @Override
    public Result<GetPositionMessageResp> getPositionMessage(Long positionId) {
        GetPositionMessageResp resp = new GetPositionMessageResp();
        Position position = recruiterCrossService.getPositionById(positionId);
        if(Objects.isNull(position)) {
            throw new NullPointerException("该岗位不存在");
        }
        Company company = recruiterCrossService.getCompanyMessage(position.getCompanyId());
        User user = userCommonService.getUserByUserId(position.getUserId());
        Recruiter recruiter = recruiterCrossService.getRecruiterByUserId(position.getUserId());
        BeanUtils.copyProperties(recruiter,resp);
        resp.setCompanyAvatar(company.getAvatar());
        resp.setCompanyName(company.getName());
        resp.setCompanyLocation(company.getLocation());
        BeanUtils.copyProperties(company,resp);
        resp.setPositionLocation(position.getLocation());
        BeanUtils.copyProperties(position,resp);
        String phone = "";
        try {
            phone = phoneNumberUtils.decryptPhone(user.getPhoneAes());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        LocalDateTime birthDate = user.getBirthDate();
        Long age=0L;
        if (birthDate!=null) {
            age = (long) Period.between(LocalDate.from(birthDate), LocalDate.now()).getYears();
        }
        resp.setPhone(phone);
        resp.setAge(age);
        BeanUtils.copyProperties(user,resp);
        return Result.success(resp);
    }

    /**
     * @Description:  使用stream.map等处理分页查询职位列表响应体
     * @param positions
     * @param users
     * @param positionPageInfo
     * @return MCrossGetPagePositionsResp
     * @Author lhb
     * @CreateTime 2025/7/12 19:25
     */
    private MCrossGetPagePositionsResp processPagePositionList(List<Position> positions,
                                                               List<User> users,
                                                               PageInfo<Position> positionPageInfo) {
        MCrossGetPagePositionsResp resp = new MCrossGetPagePositionsResp();
        resp.setRespList(new ArrayList<>());
        Map<Long, User> userMap = users.stream()
                .collect(Collectors.toMap(User::getUserId, user -> user));
        for (Position position : positions) {
            MCrossGetPagePositionResp mCrossGetPagePositionResp = new MCrossGetPagePositionResp();
            BeanUtils.copyProperties(position, mCrossGetPagePositionResp);
            User user = userMap.get(position.getUserId());
            String phone = "";
            try {
                phone=phoneNumberUtils.decryptPhone(user.getPhoneAes());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            mCrossGetPagePositionResp.setUserName(user.getName());
            mCrossGetPagePositionResp.setPhone(phone);
            resp.getRespList().add(mCrossGetPagePositionResp);
        }
        //构造响应体
        resp.setPages(positionPageInfo.getPages());
        resp.setTotal(positionPageInfo.getTotal());
        resp.setPageNum(positionPageInfo.getPageNum());
        resp.setPageSize(positionPageInfo.getPageSize());
        resp.setSize(positionPageInfo.getSize());
        return resp;
    }


    /**
     * @Description: 跨服务调用recruiter，注册岗位信息
     * @param dto
     * @param userId
     * @return boolean
     * @Author lhb
     * @CreateTime 2025/6/21 16:44
     */
    public boolean registerPublishPosition(PublishPositionDto dto,Long userId){
        String url = crossServiceBaseUrl + "/recruiter/position/registerPublishPosition";
        // 手动创建 CrossServiceInvoker 实例
        CrossServiceInvoker invoker =
                new CrossServiceInvoker(authConfig, restTemplate);
        Result<Object> result = null;
        try {
            result = invoker.invokeAndHandle(
                    url,
                    HttpMethod.POST,
                    dto,
                    Object.class,
                    userId,
                    null
            );
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result.getCode().equals(HttpServletResponse.SC_CREATED);
    }

    /**
     * @Description: 跨服务调用recruiter，变更岗位信息
     * @param req
     * @param userId
     * @return boolean
     * @Author lhb
     * @CreateTime 2025/6/21 16:47
     */
    private boolean changePositionInformation(RCrossChangePositionReq req, Long userId) throws Exception {
        String url = crossServiceBaseUrl + "/recruiter/position/changePositionInformation";
        // 手动创建 CrossServiceInvoker 实例
        CrossServiceInvoker invoker =
                new CrossServiceInvoker(authConfig, restTemplate);
        Result<Object> result = invoker.invokeAndHandle(
                url,
                HttpMethod.POST,
                req,
                Object.class,
                userId,
                null
        );
        return result.getCode().equals(HttpServletResponse.SC_CREATED);
    }


}
